/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#include "DXUT.h"
#include "GUI.h"
#include "MandelbrotMgr.h"

#define IDC_MANDELBROT_MODE_CB                            10000
#define IDC_MANDELBROT_ITERATION_TEXT                    10001
#define IDC_MANDELBROT_ITERATION_SLIDER                    10002

GUI g_gui;

void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext );


GUI::GUI() : m_pTxtHelper( NULL ), m_bDisplayGUI( true ), m_pModeCB( NULL ), m_pMaxIterationSlider( NULL )
{
}

/**
    @param pd3dDevice    [in]    D3D Device
*/
HRESULT GUI::Create( ID3D11Device* pd3dDevice )
{
    HRESULT hr = S_OK;

    ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext();
    V_RETURN( m_DialogResourceManager.OnD3D11CreateDevice( pd3dDevice, pd3dImmediateContext ) );
    m_pTxtHelper = new CDXUTTextHelper( pd3dDevice, pd3dImmediateContext, &m_DialogResourceManager, 15 );

     return hr;
}

/**
*/
void GUI::RegistGuiItems()
{
    m_SampleUI.Init( &m_DialogResourceManager );

    int nY = 150;

    // mode combobox
    m_SampleUI.AddComboBox( IDC_MANDELBROT_MODE_CB, 0, nY, 150, 24, 'M', false, &m_pModeCB );
    m_pModeCB->AddItem( L"CPU", IntToPtr(MANDELBROT_MODE_CPU) );
    m_pModeCB->AddItem( L"ComputeShader", IntToPtr(MANDELBROT_MODE_CS) );
    m_pModeCB->SetSelectedByIndex( g_mandelbrotMgr.GetMode() );
    m_pModeCB->SetTextColor( D3DCOLOR_XRGB( 0, 0, 255 ) );
    nY += 24;

    // iteration textbox and slider
    m_SampleUI.AddStatic( IDC_MANDELBROT_ITERATION_TEXT, L"Max Iterations", 0, nY, 150, 24 );
    nY += 24;
    m_SampleUI.AddSlider( IDC_MANDELBROT_ITERATION_SLIDER, 0, nY, 128, 15, 0, 1024, g_mandelbrotMgr.GetnMaxIterations(), false,  &m_pMaxIterationSlider );
    m_pMaxIterationSlider->SetValue( g_mandelbrotMgr.GetnMaxIterations() );

    m_SampleUI.SetCallback( OnGUIEvent ); 
}

/**
    @param fElapsedTime        [in]        elapsed time
*/
void GUI::FrameRender( float fElapsedTime )
{
    if( m_bDisplayGUI ) {
        m_SampleUI.OnRender( fElapsedTime );
    }
    RenderText();
}

/**
*/
void GUI::RenderText()
{
    wchar_t strMsg[ 256 ];

    m_pTxtHelper->Begin();
    m_pTxtHelper->SetInsertionPos( 2, 0 );
    m_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
    m_pTxtHelper->DrawTextLine( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) );
    m_pTxtHelper->DrawTextLine( DXUTGetDeviceStats() );

    //
    float        fScale    = g_mandelbrotMgr.GetfZoomScale();
    const ConstantBuf* pConstantBuf = g_mandelbrotMgr.GetpConstantBuf();
    swprintf_s( strMsg, L"Real: <%f,%f> Img: <%f,%f> Scale: %f Iter: %d", pConstantBuf->fMinRe, pConstantBuf->fMaxRe, pConstantBuf->fMinIm, pConstantBuf->fMaxIm, 
        fScale, pConstantBuf->nMaxIterations );
    m_pTxtHelper->DrawTextLine( strMsg );

    m_pTxtHelper->End();
}

/**
    @param pd3dDevice        [in]    D3D Device
    @param pBackBufferDesc    [in]    Description of backbuffer
*/
HRESULT GUI::ResizedSwapChain( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc )
{
    HRESULT hr = S_OK;
    V_RETURN( m_DialogResourceManager.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );

    m_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 280 );
    m_SampleUI.SetSize( 150, 110 );

    return hr;
}

/**
*/
void GUI::Destroy()
{
    m_DialogResourceManager.OnD3D11DestroyDevice();
    SAFE_DELETE( m_pTxtHelper );    
}

/**
*/
LRESULT GUI::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
{
    // Pass messages to dialog resource manager calls so GUI state is updated correctly
    *pbNoFurtherProcessing = m_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    *pbNoFurtherProcessing = m_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;    

    return 0;
}

/**
    CDXUTDialog callback.
*/
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext )
{
    switch( nControlID )
    {
    case IDC_MANDELBROT_MODE_CB:
        {
        CDXUTComboBox* pComboBox = ( CDXUTComboBox* )pControl;
        g_mandelbrotMgr.SetMode( static_cast< MandelbrotMode >( PtrToInt( pComboBox->GetSelectedData() ) ) );
        break;
        }
    case IDC_MANDELBROT_ITERATION_SLIDER:
        {
        CDXUTSlider* pSlider = ( CDXUTSlider* )pControl;
        g_mandelbrotMgr.SetnMaxIterations( pSlider->GetValue() );
        break;
        }
    }
}
